package dic

import (
	"sensitives/models/cloud"
	"sensitives/models/site"
	"sensitives/service/conf"
	"strings"
	"sync"
	"time"
)

const dictDir = "dictionary/"

type TrieTree struct {
	Node  map[string]*TrieTree `json:"node"`
	Level uint8                `json:"level"`
	IsEnd bool                 `json:"isend"`
}

type SiteTree struct {
	Sys  TrieTree `json:"sys"`
	User TrieTree `json:"user"`
}

var sites []int
var CloudMap map[int]SiteTree

func LoadDic() map[int]SiteTree {
	sites = cloud.GetSites()
	CloudMap = make(map[int]SiteTree)
	var wg sync.WaitGroup
	for _, site := range sites {
		wg.Add(1)
		go func(site int) {
			defer wg.Done()
			CloudMap[site] = SiteTree{
				Sys:  loadSiteSysDic(site),
				User: loadSiteUserDic(site),
			}
		}(site)
	}
	wg.Wait()
	return CloudMap
}

// 加载系统词库
func loadSiteSysDic(siteid int) (sysMap TrieTree) {
	sysMap = TrieTree{
		Node:  make(map[string]*TrieTree),
		Level: 0,
		IsEnd: false,
	}
	syswords := site.GetSysWords(siteid)
	for _, sysword := range syswords {
		sysMapTemp := &sysMap
		words := strings.Split(sysword.Word, "")
		lwords := len(words)
		for k, word := range words {
			if _, ok := sysMapTemp.Node[word]; !ok {
				trieTmp := new(TrieTree)
				trieTmp.Node = make(map[string]*TrieTree)
				trieTmp.IsEnd = k == (lwords - 1)
				if trieTmp.IsEnd {
					trieTmp.Level = sysword.Level
				}
				sysMapTemp.Node[word] = trieTmp
			}
			if k == (lwords - 1) {
				sysMapTemp.Node[word].IsEnd = true
			}
			sysMapTemp = sysMapTemp.Node[word]
		}
	}
	return
}

// 加载用户词库
func loadSiteUserDic(siteid int) (userMap TrieTree) {
	userMap = TrieTree{
		Node:  make(map[string]*TrieTree),
		IsEnd: false,
	}
	ugcwords := site.GetUgcWords(siteid)
	for _, ugcword := range ugcwords {
		userMapTemp := &userMap
		words := strings.Split(ugcword.Word, "")
		lwords := len(words)
		for k, word := range words {
			if _, ok := userMapTemp.Node[word]; !ok {
				trieTmp := new(TrieTree)
				trieTmp.Node = make(map[string]*TrieTree)
				trieTmp.IsEnd = k == (lwords - 1)
				if trieTmp.IsEnd {
					trieTmp.Level = ugcword.Level
				}
				userMapTemp.Node[word] = trieTmp
			}
			if k == (lwords - 1) {
				userMapTemp.Node[word].IsEnd = true
			}
			userMapTemp = userMapTemp.Node[word]
		}
	}
	return
}

// Updatedic 定时更新敏感词字典
func Updatedic() {
	var wg sync.WaitGroup
	wg.Add(1)
	ticker := time.NewTicker(time.Minute * conf.GetIntervalMinute())
	go func(t *time.Ticker) {
		defer wg.Done()
		for {
			select {
			case <-t.C:
				LoadDic()
			default:
			}
		}
	}(ticker)
	wg.Wait()
}

// LoadSiteDic 加载站点铭感词字典
func LoadSiteDic(siteid int) {
	CloudMap[siteid] = SiteTree{
		Sys:  loadSiteSysDic(siteid),
		User: loadSiteUserDic(siteid),
	}
}
